﻿using System;
using System.IO;
using System.Xml.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Soap;
using System.Web.Script.Serialization;
namespace LG.Common
{
	public static class SerializeHelper
	{  
        #region 二进制格式序列化和反序列化

        /// <summary>
        /// 把对象用二进制格式序列化到流
        /// </summary>
        /// <param name="obj">对象</param>
        /// <param name="stream">目标流</param>
        public static void BinarySerialize(object obj, Stream stream)
        {
            IFormatter formatter = new BinaryFormatter();
            formatter.Serialize(stream, obj);
        }

        /// <summary>
        /// 把对象用二进制格式序列化到文件
        /// </summary>
        /// <param name="obj">对象</param>
        /// <param name="file">对象的类型</param>
        public static void BinarySerialize(object obj, string file)
        {
            using (FileStream stream = new FileStream(file, FileMode.Create))
            {
                BinarySerialize(obj, stream);
            }
        }

        /// <summary>
        /// 从流反序列化对象
        /// </summary>
        /// <typeparam name="T">对象的类型</typeparam>
        /// <param name="stream">流</param>
        /// <returns></returns>
        public static T BinaryDeserialize<T>(Stream stream) where T : class
        {
            IFormatter formatter = new BinaryFormatter();
            object obj = formatter.Deserialize(stream);
            if (obj is T)
            {
                return obj as T;
            }
            else
            {
                Type type = typeof(T);
                throw new Exception(string.Format ("反序列化后不能得到类型{0}",type.Name));
            }
        }
        
        /// <summary>
        /// 从文件反序列化对象
        /// </summary>
        /// <typeparam name="T">对象的类型</typeparam>
        /// <param name="file">文件路径</param>
        /// <returns></returns>
        public static T BinaryDeserialize<T>(string file) where T : class
        {
            using (Stream stream = new FileStream(file, FileMode.Open, FileAccess.Read))
            {
                return BinaryDeserialize<T>(stream);
            }
        }

        #endregion

        #region Soap格式序列化和反序列化
        /// <summary>
        /// 把对象用Soap格式格式序列化到流
        /// </summary>
        /// <param name="obj">对象</param>
        /// <param name="stream">目标流</param>
        public static void SoapSerialize(object obj, Stream stream)
        {
            IFormatter formatter = new SoapFormatter();
            formatter.Serialize(stream, obj);
        }

        /// <summary>
        /// 把对象用Soap格式格式序列化到文件
        /// </summary>
        /// <param name="obj">流</param>
        /// <param name="file">文件路径</param>
        public static void SoapSerialize(object obj, string file)
        {
            using (FileStream stream = new FileStream(file, FileMode.Create))
            {
                SoapSerialize(obj, stream);
            }
        }

        /// <summary>
        /// 从流反序列化对象
        /// </summary>
        /// <typeparam name="T">对象的类型</typeparam>
        /// <param name="stream">流</param>
        /// <returns></returns>
        public static T SoapDeserialize<T>(Stream stream) where T:class
        {
            IFormatter formatter = new SoapFormatter();
            object obj = formatter.Deserialize(stream);
            if (obj is T)
            {
                return obj as T;
            }
            else
            {
                Type type = typeof(T);
                throw new Exception(string.Format("反序列化后不能得到类型{1}", type.Name));
            }
        }

        /// <summary>
        /// 从流反序列化对象
        /// </summary>
        /// <typeparam name="T">对象的类型</typeparam>
        /// <param name="file">文件路径</param>
        /// <returns></returns>
        public static T SoapDeserialize<T>(string file) where T : class
        {
            using (Stream stream = new FileStream(file, FileMode.Open, FileAccess.Read))
            {
                return SoapDeserialize<T>(stream);
            }
        }

        #endregion 

        #region Xml格式序列化和反序列化

        /// <summary>
        /// 把对象用Xml格式格式序列化到流
        /// </summary>
        /// <param name="obj">对象</param>
        /// <param name="stream">流</param>
        public static void XmlSerialize(object obj, Stream stream)
        {
            Type type = obj.GetType();
            XmlSerializer xmlSer = new XmlSerializer(type);
            xmlSer.Serialize(stream, obj);
        }

        /// <summary>
        /// 把对象用Xml格式格式序列化到文件
        /// </summary>
        /// <param name="obj">对象</param>
        /// <param name="file">文件</param>
        public static void XmlSerialize(object obj, string file)
        {
            using (Stream stream = new FileStream(file, FileMode.CreateNew, FileAccess.Write))
            {
                XmlSerialize(obj, stream);
            }
        }

        /// <summary>
        /// 从流反序列化对象
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="stream">流</param>
        /// <returns></returns>
        public static T XmlDeserialize<T>(Stream stream) where T : class
        {
            Type type = typeof(T);
            XmlSerializer xmlSer = new XmlSerializer(type);
            object obj= xmlSer.Deserialize(stream);
            if (obj is T)
            {
                return obj as T;
            }
            else
            {
                throw new Exception(string.Format("反序列化后不能得到类型{0}", type.Name));
            }
        }

        /// <summary>
        /// 从文件反序列化对象
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="file">文件</param>
        /// <returns></returns>
        public static T XmlDeserialize<T>(string file) where T : class
        {
            using (Stream stream = new FileStream(file, FileMode.Open, FileAccess.Read))
            {
                return XmlDeserialize<T>(stream);
            }
        }
        #endregion

        #region JSONServiser

        private static JavaScriptSerializer _jss;
        private static JavaScriptSerializer JSS
        {
            get {
                if (_jss == null)
                {
                    _jss = new JavaScriptSerializer();
                }
                return _jss;
            }
        }

        /// <summary>
        /// JavaScriptSerializer
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string JSONSerialize(object obj)
        {
            string result= JSS.Serialize(obj);
            return result;
        }

        /// <summary>
        /// JavaScriptSerializer
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="output"></param>
        public static void JSONSerialize(object obj, System.Text.StringBuilder output)
        {
            JSS.Serialize(obj, output);
        }

        /// <summary>
        /// JavaScriptSerializer
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="json"></param>
        /// <returns></returns>
        public static T JSONDeserialize<T>(string json)
        {
            T obj = JSS.Deserialize<T>(json);
            return obj;
        }
        
        #endregion

        /// <summary>
        /// 利用序列化克隆对象
        /// </summary>
        /// <typeparam name="T">对象的类型</typeparam>
        /// <param name="source">原对象</param>
        /// <returns></returns>
        public static T Clone<T>(T source) where T : class
        {
            if (typeof(T).IsSerializable)
            {
                using (Stream stream = new MemoryStream())
                {
                    BinarySerialize(source, stream);
                    T clone = BinaryDeserialize<T>(stream);
                    return clone;
                }
            }
            else
            {
                throw new Exception(string.Format ("不能用序列化的方式克隆类型为{0}的对象",typeof(T).Name));
            }
        }
    }
}
